<?php

class Core_Form
{
	static $_instance = null;

	public function getConfigs()
	{
		return new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', APPLICATION_ENV);
	}

	public static function getInstance()
	{
			if (null === self::$_instance) {
					self::$_instance = new self();
			}
			return self::$_instance;
	}

	public static function getForm($path, $options = array())
	{
		$basePath = APPLICATION_PATH . '/forms/'.$path;
		$file 		= APPLICATION_PATH . '/forms/'.$path.'/'.array_pop(explode('/',$path)).'.php';
		$class 		= 'Forms_'.str_replace('/', '_', $path);
		if(is_file($file))
		{
			require_once($file);
			if(class_exists($class))
			{
				$ins = new $class(self::getConfigs()->resources->view->toArray()+array('basePath'=>$basePath));
				foreach($options as $k => $v)
				{
					$ins->{$k} = $v;
				}
				return $ins;
			}
		}
		return null;
	}
	
	public static function getRender($path, $options = array(), $view = 'render.phtml')
	{
		return self::getForm($path, $options)->render($view);
	}
}

abstract class Core_Form_Abstract extends Zend_View
{
	protected $formid;
	protected $cache;
	protected $messages = array();
	protected $data = array();

	public function __construct($config)
	{
		parent::__construct($config);
		is_dir('cache/form/') or mkdir('cache/form/', 0755, true);
		$this->cache 	= Zend_Cache::factory('Core', 'File', array(
												'lifetime' => 900, 'automatic_serialization' => true
											), array(
												'cache_dir' => 'cache/form/'
										));
		$this->formid = md5($_SERVER['REMOTE_ADDR']. uniqid(mt_rand(), true));
	}
  public function getData($key = null)
  {
		$value = $this->data;
		$rules = $this->rules();
		
		if(is_null($key))
		{
			return $value;
		}
		
		$index = empty($rules[$key]['index'])?$key:$rules[$key]['index'];
    return isset($value[$key])?$value[$key]:@$value[$index];
  }
  public function setData(array $data)
  {
		$this->data = array_merge($this->data, $data);
		/*
		foreach($data as $k => $v)
			$this->data[$this->getTransform($k, true)] = $v;
		*/
		return $this;
  }
  public function clearData()
  {
		unset($this->data);
  	return $this;
  }
	public function meta()
	{
		$data['hashKey'] = md5($_SERVER['REMOTE_ADDR'] . uniqid(mt_rand(), true));

		$this->cache->save($data, 'form_'.$this->formid);

		return '
			<input type="hidden" name="formid" value="'.$this->formid.'" />
			<input type="hidden" name="formkey" value="'.$data['hashKey'].'" />';
	}
	public function validMeta()
	{
		$request 	= Zend_Controller_Front::getInstance()->getRequest();
		$data 		= $this->cache->load('form_'.@$request->getParam('formid'));
		
		if($request->getParam('formkey') !== $data['hashKey'])
		{
			$this->setMessage('_', array('Gửi dữ liệu không thành công vui lòng thử lại'));
			return false;
		}
		
		return true;
	}
	abstract public function rules();
	
	public function validate($all = true)
	{
		$value = $this->data;
		$validrules = ($all===true)?array_keys($this->rules()):explode(',', $all);
		
		foreach($this->rules() as $key => $rules)
		if(@in_array($key, $validrules))
		if(@is_array($rules['valid']))
		{
			$validators = new Zend_Validate();
			foreach($rules['valid'] as $rule)
				$validators->addValidator($rule);
			
			
			if(!$validators->isValid($this->getData($key)))
			{
				$this->setMessage($key, @array_values($validators->getMessages()));
			}
		}
		return !$this->hasMessage();
	}
	public function valid($data = array(), $valids = array())
	{
		$messages = array();
		
		foreach($valids as $key => $rules)
		{
			$validators = new Zend_Validate();
			foreach($rules as $rule)
				$validators->addValidator($rule);
			
			
			if(!$validators->isValid($data[$key]))
			{
				$messages[$key] = $validators->getMessages();
			}
		}
		return $messages;
	}
	public function filter($keys = null, $inkeys = true)
  {
		$value = $this->data;
		$rules = $this->rules();

		if(is_null($keys))
		{
			$data = array();
			foreach($rules as $key => $rule)
			{
				$index = empty($rule['index'])?$key:$rule['index'];
				$data[$index] = isset($value[$key])?$value[$key]:@$value[$index];
				//$data[$key] = $value[$key];
				if(@is_array($rule['filter']))
				{
					foreach($rule['filter'] as $filter)
						$data[$index] = $filter->filter($data[$index]);
				}
			}
		}
		elseif(is_array($keys))
		{
			$data = array();
			foreach($rules as $key => $rule)
			if(($inkeys && in_array($key, $keys))||(!$inkeys && !in_array($key, $keys)))
			{
				$index = empty($rule['index'])?$key:$rule['index'];
				$data[$index] = isset($value[$key])?$value[$key]:@$value[$index];
				//$data[$key] = $value[$key];
				if(@is_array($rule['filter']))
				{
					foreach($rule['filter'] as $filter)
						$data[$index] = $filter->filter($data[$index]);
				}
			}
		}
		else
		{
			
			$index = empty($rules[$keys]['index'])?$keys:$rules[$keys]['index'];
			$data = isset($value[$keys])?$value[$keys]:@$value[$index];
			//$data[$key] = $value[$key];
			if(is_array(@$rules[$keys]['filter']))
			{
				foreach($rules[$keys]['filter'] as $filter)
					$data = $filter->filter($data);
			}
		}
		return $data;
  }
	public function hasMessage($index = null)
  {
    $messages = $this->messages;

    if($index === null)
    {
      return empty($messages)?false:true;
    }
    return empty($messages[$index])?false:true;
  }

  public function getMessage($index = null)
  {
    return ($index === null)?$this->messages:@$this->messages[$index];
  }
  
  public function setMessage($key, $val = null)
  {
    $stores   = $this->messages;
    $messages = is_array($key)?$key:array($key=>$val);
    
    foreach($messages as $k=>$v)
      $stores[$k] = $v;
    
    $this->messages = $stores;
    return $this;
  }
  
  public function clearMessage()
  {
   $this->messages = array(); 
   return $this;
  }
	public function render($name = 'render.phtml')
	{
		return parent::render($name);
	}
}